package com.dsteiner.gwt.cafeteriasophia.client.controller;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

import com.dsteiner.gwt.cafeteriasophia.client.domain.Product;
import com.dsteiner.gwt.cafeteriasophia.client.domain.Purchase;
import com.dsteiner.gwt.cafeteriasophia.client.domain.Sale;
import com.dsteiner.gwt.cafeteriasophia.client.domain.Stock;
import com.dsteiner.gwt.cafeteriasophia.client.model.ProductModel;
import com.dsteiner.gwt.cafeteriasophia.client.model.PurchaseModel;
import com.dsteiner.gwt.cafeteriasophia.client.model.SaleLineModel;
import com.dsteiner.widgets.client.JsUtil;
import com.dsteiner.widgets.client.ObjectUtil;
import com.dsteiner.widgets.client.Widgets.FlowPanelExt;
import com.dsteiner.widgets.client.Widgets.HorizontalPanelExt;
import com.dsteiner.widgets.client.Widgets.IFlowPanel;
import com.dsteiner.widgets.client.Widgets.IHTML;
import com.dsteiner.widgets.client.Widgets.ILazyWidget;
import com.dsteiner.widgets.client.Widgets.IWidget;
import com.dsteiner.widgets.client.Widgets.IWidgetBuilder;
import com.dsteiner.widgets.client.Widgets.WidgetListenerAdapter;
import com.dsteiner.widgets.client.model.PrefilledTextBoxModel;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;

public class ProductController {

	private ProductModel productModel;
	private IHTML titleHtml;
	private PrefilledTextBoxModel stockTextBoxModel;
	private IWidget stockLine;
	private IFlowPanel salesWidgetCotentPanel;
	private IHTML reduceSaleWidgetLink;
	private IHTML addSaleWidgetLink;
	private IWidgetBuilder widgetBuilder;
	private IFlowPanel salePanel;
	private IFlowPanel purchasesWidgetContentPanel;
	private IWidget incomeLine;

	public void registerAddSaleWidgetLink(IHTML addSaleWidgetLink) {
		this.addSaleWidgetLink = addSaleWidgetLink;
		addSaleWidgetLink.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event) {
				productModel.addSale(createSale());
			}
		});
	}

	public void registerProductModel(ProductModel productModel) {
		this.productModel = productModel;
		productModel.addPropertyChangeListener("product", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updateProduct();
			}
		});
		productModel.addPropertyChangeListener("sales", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updateSales();
				updateSalesLinks();
			}
		});
		productModel.addPropertyChangeListener("stock", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updateStock();
			}
		});
		productModel.addPropertyChangeListener("purchases", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updatePurchases();
			}
		});
	}

	public void registerProductWidget(ILazyWidget productWidget) {
		productWidget.addWidgetListener(new WidgetListenerAdapter() {
			@Override
			public void onAttach(IWidget widget) {
				if(productModel.getSales() == null || productModel.getSales().isEmpty()){
					productModel.setSales(new ArrayList<Sale>());
					if(productModel.getProduct().isSaleable())
						productModel.addSale(createSale());
				}
				if(productModel.getPurchases() == null || productModel.getPurchases().isEmpty()){
					productModel.setPurchases(new ArrayList<Purchase>());
					productModel.addPurchase(createPurchase());
				}
				if(productModel.getStock() == null){
					productModel.setStock(createStock());
				}
				updateProduct();
				updateSales();
				updateSalesLinks();
				updatePurchases();
				updateStock();
			}
		});
	}

	public void registerReduceSaleWidgetLink(IHTML reduceSaleWidgetLink) {
		this.reduceSaleWidgetLink = reduceSaleWidgetLink;
		reduceSaleWidgetLink.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event) {
				productModel.removeSale();
			}
		});
	}

	public void registerSalesWidgetContentPanel(IFlowPanel salesWidgetCotentPanel) {
		this.salesWidgetCotentPanel = salesWidgetCotentPanel;
	}

	public void registerStockLine(IWidget stockLine) {
		this.stockLine = stockLine;
	}

	public void registerStockTextBoxModel(final PrefilledTextBoxModel stockTextBoxModel) {
		this.stockTextBoxModel = stockTextBoxModel;
		stockTextBoxModel.addPropertyChangeListener("hasFocus", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				if(!stockTextBoxModel.hasFocus()){
					String text = stockTextBoxModel.getText();
					if(stockTextBoxModel.isEdited() && !ObjectUtil.isDouble(text)){
						JsUtil.getInstance().showAlert("ingrese un numero (por ejemplo 4.0)");
						stockTextBoxModel.setText(null);
						return;
					}
					Stock stock = productModel.getStock();
					stock.setAmount(stockTextBoxModel.isEdited() ? new Double(text) : 0);
					
				}
			}
		});
	}

	public void registerTitleHtml(IHTML titleHtml) {
		this.titleHtml = titleHtml;
	}

	public void registerWidgetBuilder(IWidgetBuilder widgetBuilder) {
		this.widgetBuilder = widgetBuilder;
	}

	private Purchase createPurchase() {
		Purchase purchase = new Purchase();
		Product product = productModel.getProduct();
		purchase.setProduct(product);
		purchase.setPrice(product.getCost() != null ? product.getCost() : 0);
		return purchase;
	}
	
	private Stock createStock() {
		Stock stock = new Stock();
		Product product = productModel.getProduct();
		stock.setProduct(product);
		return stock;
	}

	private Sale createSale() {
		Sale sale = new Sale();
		Product product = productModel.getProduct();
		sale.setPrice(product.getDefaultPrice() != null ? product.getDefaultPrice() : 0);
		sale.setProduct(productModel.getProduct());
		return sale;
	}
	
	private void updateProduct() {
		Product product = productModel.getProduct();
		if(product == null)
			return;
		
		String name = product.getName();
		titleHtml.setHTML(name + (product.getMetric() != null ? " ("+product.getMetric()+")" : ""));
		
		stockLine.setVisible(product.isStockable());
		purchasesWidgetContentPanel.setVisible(product.isStockable());
		salePanel.setVisible(product.isSaleable());
		incomeLine.setVisible(product.equals(Product.dinero));
	}

	private void updateSales() {
		List<Sale> sales = productModel.getSales();
		salesWidgetCotentPanel.clear();
		for (Sale sale : sales) {
			SaleLineModel saleLineModel = new SaleLineModel();
			saleLineModel.setSale(sale);
			IWidget createWidget = widgetBuilder.createWidget(saleLineModel);
			salesWidgetCotentPanel.add(createWidget);
		}
	}
	
	private void updateStock(){
		Stock stock = productModel.getStock();
		stockTextBoxModel.setText(stock != null && stock.getAmount() > 0 ? stock.getAmount()+"" : null);
	}
	
	private void updatePurchases() {
		List<Purchase> purchases = productModel.getPurchases();
		purchasesWidgetContentPanel.clear();
		for (Purchase purchase : purchases) {
			PurchaseModel purchaseModel = new PurchaseModel();
			purchaseModel.setPurchase(purchase);
			IWidget createWidget = widgetBuilder.createWidget(purchaseModel);
			purchasesWidgetContentPanel.add(createWidget);
		}
	}

	private void updateSalesLinks() {
		List<Sale> sales = productModel.getSales();
		Product product = productModel.getProduct();
		addSaleWidgetLink.setVisible(product.getDefaultPrice() != null);
		reduceSaleWidgetLink.setVisible(sales.size() > 1);
	}

	public void registerSalePanel(IFlowPanel salePanel) {
		this.salePanel = salePanel;
	}

	public void registerPurchasesWidgetContentPanel(IFlowPanel purchasesWidgetContentPanel) {
		this.purchasesWidgetContentPanel = purchasesWidgetContentPanel;
	}

	public void registerIncomeTextBoxModel(final PrefilledTextBoxModel incomeTextBoxModel) {
		incomeTextBoxModel.addPropertyChangeListener("hasFocus", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				if(!incomeTextBoxModel.hasFocus()){
					String text = incomeTextBoxModel.getText();
					if(incomeTextBoxModel.isEdited() && !ObjectUtil.isDouble(text)){
						JsUtil.getInstance().showAlert("ingrese un numero (por ejemplo 4.5)");
						incomeTextBoxModel.setText(null);
						return;
					}
					Sale sale = createSale();
					sale.setAmount(incomeTextBoxModel.isEdited() ? new Double(text) : 0);
					productModel.setSales(new ArrayList<Sale>());
					productModel.addSale(sale);
				}
			}
		});
	}

	public void registerIncomeLine(IWidget incomeLine) {
		this.incomeLine = incomeLine;
	}
}